package com.dev.widget.qrcode.core;

import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;

import net.sourceforge.zbar.Symbol;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.media.camera.CameraKit;
import ohos.media.camera.device.Camera;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.device.CameraStateCallback;
import ohos.media.camera.device.FrameConfig;
import ohos.media.common.BufferInfo;
import ohos.media.image.ImageReceiver;
import ohos.media.image.common.ImageFormat;

import java.nio.ByteBuffer;

import static ohos.media.camera.device.Camera.FrameConfigType.FRAME_CONFIG_PREVIEW;
import static ohos.media.camera.params.Metadata.FlashMode.FLASH_ALWAYS_OPEN;
import static ohos.media.camera.params.Metadata.FlashMode.FLASH_CLOSE;

public class ZbarView {
    private ImageScanner scanner;
    private ImageReceiver imageReceiver;
    private CameraKit cameraKit;
    private Surface previewSurface;
    private Surface dataSurface;
    private Camera mcamera;
    private EventHandler handler;
    public static final int VIDEO_WIDTH = 1080;
    public static final int VIDEO_HEIGHT = 1920;
    private Context context;
    private OnZbarCameraScanner cameraScanner;
    private FrameConfig.Builder frameConfigBuilder;
    private SurfaceProvider surfaceProvider;
    private int timeLine=0;
    private ohos.media.image.Image mImage;

    public ZbarView(Context context, SurfaceProvider surfaceProvider) {
        this.surfaceProvider = surfaceProvider;
        this.context = context;
        handler = new EventHandler(EventRunner.getMainEventRunner());
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);
        surfaceProvider.pinToZTop(false);
        imageReceiver = ImageReceiver.create(VIDEO_WIDTH ,VIDEO_HEIGHT,  ImageFormat.YUV420_888, 10);
        imageReceiver.setImageArrivalListener(new IImageArrivalListenerImpl());
        surfaceProvider.getSurfaceOps().get().addCallback(new SurfaceOps.Callback() {
            @Override
            public void surfaceCreated(SurfaceOps surfaceOps) {
                surfaceProvider.getSurfaceOps().get().setFixedSize(VIDEO_HEIGHT , VIDEO_WIDTH );
                previewSurface = surfaceOps.getSurface();
                openCamera();
            }

            @Override
            public void surfaceChanged(SurfaceOps surfaceOps, int i, int i1, int i2) {

            }

            @Override
            public void surfaceDestroyed(SurfaceOps surfaceOps) {

            }
        });

    }



    private class IImageArrivalListenerImpl implements ImageReceiver.IImageArrivalListener {
        //对监听事件的响应逻辑，实现对图像数据处理和到编码器的传输
        @Override
        public void onImageArrival(ImageReceiver imageReceiver) {

             mImage = imageReceiver.readNextImage();
            timeLine++;
            //灵敏度处理
            if(timeLine<50){
                mImage.release();
                return;
            }
            if (mImage != null) {
                timeLine=0;
                BufferInfo bufferInfo = new BufferInfo();
                ByteBuffer mBuffer;
                byte[] YUV_DATA = new byte[VIDEO_HEIGHT * VIDEO_WIDTH * 3 / 2];
                int i;
                //采集YUV格式数据
                mBuffer = mImage.getComponent(ImageFormat.ComponentType.YUV_Y).getBuffer();
                for (i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT; i++) {
                    YUV_DATA[i] = mBuffer.get(i);
                }
                mBuffer = mImage.getComponent(ImageFormat.ComponentType.YUV_V).getBuffer();
                for (i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT / 4; i++) {
                    YUV_DATA[(VIDEO_WIDTH * VIDEO_HEIGHT) + i * 2] =
                            mBuffer.get(i * 2);
                }
                mBuffer = mImage.getComponent(ImageFormat.ComponentType.YUV_U).getBuffer();
                for (i = 0; i < VIDEO_WIDTH * VIDEO_HEIGHT / 4; i++) {
                    YUV_DATA[(VIDEO_WIDTH * VIDEO_HEIGHT) + i * 2 + 1] = mBuffer.get(i * 2);
                }
                bufferInfo.setInfo(0, VIDEO_WIDTH * VIDEO_HEIGHT * 3 / 2, mImage.getTimestamp(), 0);
                Image barcode = new Image(mImage.getImageSize().width, mImage.getImageSize().height, "Y800");
                barcode.setData(YUV_DATA);


                if (scanner.scanImage(barcode) != 0) {
                    for (Symbol sym : scanner.getResults()) {
                        handler.postTask(() -> cameraScanner.getResult(sym.getData()));
                    }
                }
                mImage.release();
                return;
            }
        }
    }

    /**
     * 打开相机
     */
    public void openCamera() {
        // 获取 CameraKit 对象
        cameraKit = CameraKit.getInstance(surfaceProvider.getContext());
        if (cameraKit == null) {
            return;
        }
        try {
            // 获取当前设备的逻辑相机列表cameraIds
            String[] cameraIds = cameraKit.getCameraIds();
            // 创建相机！
            cameraKit.createCamera(cameraIds[0], new CameraStateCallbackImpl(), new EventHandler(EventRunner.create("CameraBackground")));
        } catch (IllegalStateException e) {
            System.out.println("getCameraIds fail");
        }
        if(mImage!=null){
            mImage.release();
        }
    }

    private final class CameraStateCallbackImpl extends CameraStateCallback {
        //相机回调
        @Override
        public void onCreated(Camera camera) {
            mcamera = camera;
            //相机创建时回调
            CameraConfig.Builder cameraConfigBuilder = camera.getCameraConfigBuilder();
            if (cameraConfigBuilder == null) {
                return;
            }
            // 配置预览的 Surface
            cameraConfigBuilder.addSurface(previewSurface);
            // 配置拍照的 Surface
            dataSurface = imageReceiver.getRecevingSurface();
            cameraConfigBuilder.addSurface(dataSurface);
            try {
                // 相机设备配置
                camera.configure(cameraConfigBuilder.build());
            } catch (IllegalArgumentException e) {
                System.out.println("Argument Exception");
            } catch (IllegalStateException e) {
                System.out.println("State Exception");
            }
        }

        @Override
        public void onConfigured(Camera camera) {
            frameConfigBuilder = mcamera.getFrameConfigBuilder(FRAME_CONFIG_PREVIEW);
            // 配置预览 Surface
            frameConfigBuilder.addSurface(previewSurface);
            // 配置拍照的 Surface
            frameConfigBuilder.addSurface(dataSurface);
            try {
                // 启动循环帧捕获
                mcamera.triggerLoopingCapture(frameConfigBuilder.build());
            } catch (IllegalArgumentException e) {
                System.out.println("Argument Exception");
            } catch (IllegalStateException e) {
                System.out.println("State Exception");
            }
            //相机配置
        }

        @Override
        public void onReleased(Camera camera) {
            // 释放相机设备
//            if (mcamera != null) {
//                mcamera.stopLoopingCapture();
//                mcamera.release();
//                mcamera = null;
//            }
        }
    }

    public void stopCamera() {
        if (mcamera != null) {
            mcamera.stopLoopingCapture();
            mcamera.release();
        }
    }

    /**
     * 打开闪光灯
     */
    public void openFlashlight() {
        if (frameConfigBuilder == null) {
            return;
        }
        new EventHandler(EventRunner.create("openFlashlight")).postTask(new Runnable() {
            @Override
            public void run() {
                frameConfigBuilder.setFlashMode(FLASH_ALWAYS_OPEN);
                mcamera.triggerLoopingCapture(frameConfigBuilder.build());
            }
        }, (mcamera != null && frameConfigBuilder != null) ? 0 : 500);
    }

    /**
     * 关闭闪光灯
     */
    public void closeFlashlight() {
        frameConfigBuilder.setFlashMode(FLASH_CLOSE);
        mcamera.triggerLoopingCapture(frameConfigBuilder.build());
        ;
    }

    public void setCameraScanner(OnZbarCameraScanner cameraScanner) {
        this.cameraScanner = cameraScanner;
    }

    public interface OnZbarCameraScanner {
        public void getResult(String result);
    }
}
